package com.supermap.hn.traffic.controller;

import com.alibaba.fastjson.JSONObject;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicParameters;
import com.github.xiaoymin.knife4j.annotations.DynamicResponseParameters;
import com.supermap.hn.traffic.commontype.LimitParameter;
import com.supermap.hn.traffic.commontype.LimitSpeedResult;
import com.supermap.hn.traffic.config.ESConfig;
import com.supermap.hn.traffic.services.SSCMatchService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@Api(tags = "网络匹配模块")
@CrossOrigin
@Controller
@RequestMapping("/")
public class MatchingController {
    @Autowired
    private SSCMatchService sscmatchService;
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @ApiOperationSupport(
            params = @DynamicParameters(properties = {
                    @DynamicParameter(name = "LimitParameter", value = "限速查询参数", dataTypeClass = LimitParameter.class)
            }),
            responses = @DynamicResponseParameters(properties = {
                    @DynamicParameter(value = "限速查询结果", dataTypeClass = LimitSpeedResult.class)
            })
    )
    @ApiOperation(value = "道路限速")
    @PostMapping(value = "limit", produces = "application/json")
    @ResponseBody
    public LimitSpeedResult getSpeedLimit(@RequestBody LimitParameter limitParam) {
        ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attr.getRequest();

        Long beginTime = new Date().getTime();
        //请求经纬度参数异常判断
        Boolean isOutOfChina = outOfChina(limitParam.point.x, limitParam.point.y);
        if (isOutOfChina) {
            LimitSpeedResult limitSpeedResult = new LimitSpeedResult();
            limitSpeedResult.code = "400";
            limitSpeedResult.message = "请求失败,经纬度参数异常";
            recordLog(request.getRemoteAddr(), limitParam, -1, 0L, "400");
            return limitSpeedResult;
        }

        LimitSpeedResult speedLimit = new LimitSpeedResult();

        try {
            speedLimit = sscmatchService.getSpeedLimit(limitParam);
           // speedLimit = sscmatchService.asynGetSpeedLimit(limitParam);
            Long handlingTime = new Date().getTime() - beginTime;
            //TODO 要上下行判断记录返回速度值
            int speed = speedLimit.upSpeed;
            if(speed ==- 1){
                speed = speedLimit.downSpeed;
            }
            recordLog(request.getRemoteAddr(), limitParam, speed, handlingTime, "200");
            speedLimit.code = "200";
            speedLimit.message = "请求成功";

            return speedLimit;

        } catch (IOException e) {
            recordLog(request.getRemoteAddr(), limitParam, -1, 0L, "500");
            LimitSpeedResult limitSpeedResult = new LimitSpeedResult();
            limitSpeedResult.code = "500";
            limitSpeedResult.message = "请求失败";
            return limitSpeedResult;
        }


    }

    //记录访问日志
    public void recordLog(String ip, LimitParameter limitParam, int limitSpeed, Long handlingTime, String code) {
        IndexRequest indexRequest = new IndexRequest(ESConfig.LOG_INDEX);
        indexRequest.type("_doc");
        JSONObject jsonObject = new JSONObject();
        JSONObject point = new JSONObject();
        point.put("lon", limitParam.point.x);
        point.put("lat", limitParam.point.y);
        jsonObject.put("gps", point);
        jsonObject.put("time", limitParam.point.time);
        jsonObject.put("vehicleNo", limitParam.vehicleNo);
        jsonObject.put("limitSpeed", limitSpeed);
        jsonObject.put("ipAddr", ip);
        jsonObject.put("code", code);
        jsonObject.put("handlingTime", handlingTime);
        indexRequest.source(jsonObject, XContentType.JSON);
        try {
            IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 判断坐标是否不在国内
     *
     * @param lng 经度
     * @param lat 纬度
     * @return 坐标是否在国内
     */
    public static boolean outOfChina(double lng, double lat) {
        return (lng < 72.004 || lng > 137.8347) || (lat < 0.8293 || lat > 55.8271);
    }


    @ApiOperationSupport(
            params = @DynamicParameters(properties = {
                    @DynamicParameter(name = "LimitParameter", value = "限速查询参数", dataTypeClass = LimitParameter.class)
            }),
            responses = @DynamicResponseParameters(properties = {
                    @DynamicParameter(value = "限速查询结果", dataTypeClass = LimitSpeedResult.class)
            })
    )
    @ApiOperation(value = "道路限速")
    @PostMapping(value = "limit2", produces = "application/json")
    @ResponseBody
    public LimitSpeedResult getSpeedLimit2(@RequestBody LimitParameter limitParam) throws IOException {
        ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attr.getRequest();

        Long beginTime = new Date().getTime();
        //请求经纬度参数异常判断
        Boolean isOutOfChina = outOfChina(limitParam.point.x, limitParam.point.y);
        if (isOutOfChina) {
            LimitSpeedResult limitSpeedResult = new LimitSpeedResult();
            limitSpeedResult.code = "400";
            limitSpeedResult.message = "请求失败,经纬度参数异常";
            recordLog(request.getRemoteAddr(), limitParam, -1, 0L, "400");
            return limitSpeedResult;
        }

        Future<LimitSpeedResult> speedLimit = null;

        try {
            speedLimit =  sscmatchService.asynGetSpeedLimit(limitParam);
            // speedLimit = sscmatchService.asynGetSpeedLimit(limitParam);
           Long handlingTime = new Date().getTime() - beginTime;
            //TODO 要上下行判断记录返回速度值
            int speed = speedLimit.get().upSpeed;
            if(speed ==- 1){
                speed = speedLimit.get().downSpeed;
            }
            recordLog(request.getRemoteAddr(), limitParam, speed, handlingTime, "200");
            speedLimit.get().code = "200";
            speedLimit.get().message = "请求成功";

            return speedLimit.get();

        } catch (Exception e) {
            recordLog(request.getRemoteAddr(), limitParam, -1, 0L, "500");
            LimitSpeedResult limitSpeedResult = new LimitSpeedResult();
            limitSpeedResult.code = "500";
            limitSpeedResult.message = "请求失败";
            return limitSpeedResult;
        }
    }

    @ApiOperationSupport(
            params = @DynamicParameters(properties = {
                    @DynamicParameter(name = "LimitParameter", value = "限速查询参数", dataTypeClass = LimitParameter.class)
            }),
            responses = @DynamicResponseParameters(properties = {
                    @DynamicParameter(value = "限速查询结果", dataTypeClass = LimitSpeedResult.class)
            })
    )
    @ApiOperation(value = "批量道路限速")
    @PostMapping(value = "limit3", produces = "application/json")
    @ResponseBody
    public LimitSpeedResult getSpeedLimit3(@RequestBody LimitParameter limitParam) throws IOException {
        return  sscmatchService.batchMatch(limitParam);

    }

    @ApiOperationSupport(
            params = @DynamicParameters(properties = {
                    @DynamicParameter(name = "LimitParameter", value = "限速查询参数", dataTypeClass = LimitParameter.class)
            }),
            responses = @DynamicResponseParameters(properties = {
                    @DynamicParameter(value = "限速查询结果", dataTypeClass = LimitSpeedResult.class)
            })
    )
    @ApiOperation(value = "多线程测试")
    @PostMapping(value = "limitTest", produces = "application/json")
    @ResponseBody
    public LimitSpeedResult getSpeedLimitTest(@RequestBody LimitParameter limitParam)  {
        ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attr.getRequest();

        Long beginTime = new Date().getTime();
        //请求经纬度参数异常判断
        Boolean isOutOfChina = outOfChina(limitParam.point.x, limitParam.point.y);
        if (isOutOfChina) {
            LimitSpeedResult limitSpeedResult = new LimitSpeedResult();
            limitSpeedResult.code = "400";
            limitSpeedResult.message = "请求失败,经纬度参数异常";
            recordLog(request.getRemoteAddr(), limitParam, -1, 0L, "400");
            return limitSpeedResult;
        }

        LimitSpeedResult speedLimit;

        try {
            //speedLimit = sscmatchService.getSpeedLimit(limitParam);
            speedLimit = sscmatchService.match(limitParam).get();
            Long handlingTime = new Date().getTime() - beginTime;
            //TODO 要上下行判断记录返回速度值
            int speed = speedLimit.upSpeed;
            if(speed ==- 1){
                speed = speedLimit.downSpeed;
            }
            //recordLog(request.getRemoteAddr(), limitParam, speed, handlingTime, "200");
            speedLimit.code = "200";
            speedLimit.message = "请求成功";

            return speedLimit;

        } catch (Exception e) {
           // recordLog(request.getRemoteAddr(), limitParam, -1, 0L, "500");
            LimitSpeedResult limitSpeedResult = new LimitSpeedResult();
            limitSpeedResult.code = "500";
            limitSpeedResult.message = "请求失败";
            return limitSpeedResult;
        }


    }

}
